// ---------------------------------------------------------------
// a memory id tracks the provenance of arena/OS allocated memory
// ---------------------------------------------------------------

pub type mi_arena_id_t = i64;

// Memory can reside in arena's, direct OS allocated, or statically allocated. The memid keeps track of this.
#[derive(PartialEq, Eq)]
enum MiMemkind {
    MI_MEM_NONE,      // not allocated
    MI_MEM_EXTERNAL,  // not owned by mimalloc but provided externally (via `mi_manage_os_memory` for example)
    MI_MEM_STATIC,    // allocated in a static area and should not be freed (for arena meta data for example)
    MI_MEM_OS,        // allocated from the OS
    MI_MEM_OS_HUGE,   // allocated as huge OS pages (usually 1GiB, pinned to physical memory)
    MI_MEM_OS_REMAP,  // allocated in a remapable area (i.e. using `mremap`)
    MI_MEM_ARENA      // allocated from an arena (the usual case)
}
  
pub fn mi_memkind_is_os(memkind: MiMemkind) -> bool {
    memkind == MiMemkind::MI_MEM_OS || memkind == MiMemkind::MI_MEM_OS_HUGE || memkind == MiMemkind::MI_MEM_OS_REMAP
}
  
pub struct MiMemidOSInfo {
    base: *mut u8,               // actual base address of the block (used for offset aligned allocations)
    alignment: usize,      // alignment at allocation
}
  
pub struct MiMemidArenaInfo {
    block_index: usize,        // index in the arena
    id: mi_arena_id_t,                 // arena id (>= 1)
    is_exclusive: bool,       // this arena can only be used for specific arena allocations
}

pub enum MemInfo {
    OS(MiMemidOSInfo),
    Arena(MiMemidArenaInfo),
}
  
pub struct MiMemid {
    mem: MemInfo,
    is_pinned: bool,          // `true` if we cannot decommit/reset/protect in this memory (e.g. when allocated using large (2Mib) or huge (1GiB) OS pages)
    initially_committed: bool,// `true` if the memory was originally allocated as committed
    initially_zero: bool,     // `true` if the memory was originally zero initialized
    memkind: MiMemkind,
}
  